package com.hifar.sso.service.impl;

import com.hifar.sso.model.*;
import com.hifar.sso.service.SSOAuthService;
import com.hifar.sso.service.SSOTokenService;
import com.hifar.sso.service.SSOUserService;
import com.hifar.sso.util.JWTUtil;
import com.hifar.sso.util.SSOConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * SSO认证服务实现类
 *
 * @author system
 * @since 1.0.0
 */
@Service
public class SSOAuthServiceImpl implements SSOAuthService {

    private static final Logger logger = LoggerFactory.getLogger(SSOAuthServiceImpl.class);

    @Autowired
    private SSOUserService userService;

    @Autowired
    private SSOTokenService tokenService;

    @Override
    public SSOResponse authenticate(SSORequest request) {
        try {
            logger.info("开始用户认证，用户名: {}", request.getUsername());

            // 参数验证
            if (!StringUtils.hasText(request.getUsername()) || !StringUtils.hasText(request.getPassword())) {
                return SSOResponse.error(400, "用户名和密码不能为空");
            }

            // 用户认证
            SSOUser user = userService.authenticate(request.getUsername(), request.getPassword());
            if (user == null) {
                logger.warn("用户认证失败，用户名: {}", request.getUsername());
                return SSOResponse.error(401, "用户名或密码错误");
            }
            // 生成令牌
            SSOToken token = generateToken(user, request.getClientId());

            // 更新最后登录时间
            user.setLastLoginTime(new Date());
            userService.updateUser(user);

            logger.info("用户认证成功，用户ID: {}", user.getUserId());
            return SSOResponse.success("认证成功", user, token);

        } catch (Exception e) {
            logger.error("用户认证异常", e);
            return SSOResponse.error(500, "认证服务异常");
        }
    }

    @Override
    public String generateAuthorizationCode(SSORequest request) {
        try {
            logger.info("生成授权码，客户端ID: {}", request.getClientId());

            // 验证客户端
            if (!validateClient(request.getClientId(), request.getClientSecret())) {
                throw new IllegalArgumentException("无效的客户端");
            }

            // 验证重定向URI
            if (!validateRedirectUri(request.getClientId(), request.getRedirectUri())) {
                throw new IllegalArgumentException("无效的重定向URI");
            }

            // 生成授权码
            String code = UUID.randomUUID().toString().replace("-", "");

            // 存储授权码
            tokenService.storeAuthorizationCode(code, request.getUsername(), request.getClientId(),
                    request.getRedirectUri(), request.getScope());

            logger.info("授权码生成成功: {}", code);
            return code;

        } catch (Exception e) {
            logger.error("生成授权码异常", e);
            throw new RuntimeException("生成授权码失败", e);
        }
    }

    @Override
    public SSOToken getTokenByCode(String code, String clientId, String redirectUri) {
        try {
            logger.info("通过授权码获取令牌，授权码: {}", code);

            // 验证授权码
            SSOToken authCode = tokenService.getAuthorizationCode(code);
            if (authCode == null || authCode.isExpired()) {
                throw new IllegalArgumentException("无效或过期的授权码");
            }

            // 验证客户端
            if (!clientId.equals(authCode.getClientId())) {
                throw new IllegalArgumentException("客户端ID不匹配");
            }

            // 验证重定向URI
            if (!redirectUri.equals(authCode.getScope())) {
                throw new IllegalArgumentException("重定向URI不匹配");
            }

            // 获取用户信息
            SSOUser user = userService.getUserByUsername(authCode.getUserId());
            if (user == null) {
                throw new IllegalArgumentException("用户不存在");
            }

            // 生成访问令牌
            SSOToken accessToken = generateToken(user, clientId);

            // 标记授权码为已使用
            authCode.setUsed(true);
            tokenService.updateToken(authCode);

            logger.info("令牌生成成功，用户ID: {}", user.getUserId());
            return accessToken;

        } catch (Exception e) {
            logger.error("通过授权码获取令牌异常", e);
            throw new RuntimeException("获取令牌失败", e);
        }
    }

    @Override
    public SSOToken refreshToken(String refreshToken, String clientId) {
        try {
            logger.info("刷新令牌，客户端ID: {}", clientId);

            // 验证刷新令牌
            SSOToken token = tokenService.getTokenByRefreshToken(refreshToken);
            if (token == null || token.isExpired()) {
                throw new IllegalArgumentException("无效或过期的刷新令牌");
            }

            // 验证客户端
            if (!clientId.equals(token.getClientId())) {
                throw new IllegalArgumentException("客户端ID不匹配");
            }

            // 获取用户信息
            SSOUser user = userService.getUserById(token.getUserId());
            if (user == null) {
                throw new IllegalArgumentException("用户不存在");
            }

            // 生成新的访问令牌
            SSOToken newToken = generateToken(user, clientId);

            // 撤销旧令牌
            tokenService.revokeToken(token.getAccessToken());

            logger.info("令牌刷新成功，用户ID: {}", user.getUserId());
            return newToken;

        } catch (Exception e) {
            logger.error("刷新令牌异常", e);
            throw new RuntimeException("刷新令牌失败", e);
        }
    }

    @Override
    public SSOUser validateToken(String accessToken) {
        try {
            logger.debug("验证令牌: {}", accessToken);

            // 从缓存或数据库获取令牌信息
            SSOToken token = tokenService.getTokenByAccessToken(accessToken);
            if (token == null || token.isExpired() || token.getUsed()) {
                return null;
            }

            // 解析JWT令牌获取用户信息
            String userId = JWTUtil.getUserIdFromToken(accessToken);
            if (userId == null) {
                return null;
            }

            // 获取用户信息
            SSOUser user = userService.getUserById(userId);
            if (user == null || user.getStatus() != 1) {
                return null;
            }

            return user;

        } catch (Exception e) {
            logger.error("验证令牌异常", e);
            return null;
        }
    }

    @Override
    public boolean revokeToken(String accessToken) {
        try {
            logger.info("撤销令牌: {}", accessToken);
            return tokenService.revokeToken(accessToken);
        } catch (Exception e) {
            logger.error("撤销令牌异常", e);
            return false;
        }
    }

    @Override
    public boolean logout(String userId) {
        try {
            logger.info("用户登出，用户ID: {}", userId);

            // 撤销用户所有令牌
            tokenService.revokeUserTokens(userId);

            // 记录登出日志
            logger.info("用户登出成功，用户ID: {}", userId);
            return true;

        } catch (Exception e) {
            logger.error("用户登出异常", e);
            return false;
        }
    }

    @Override
    public SSOUser getUserInfo(String userId) {
        try {
            return userService.getUserById(userId);
        } catch (Exception e) {
            logger.error("获取用户信息异常", e);
            return null;
        }
    }

    @Override
    public SSOUser getUserById(String userId) {
        try {
            return userService.getUserById(userId);
        } catch (Exception e) {
            logger.error("根据用户ID获取用户信息异常", e);
            return null;
        }
    }

    @Override
    public List<String> getUserPermissions(String userId) {
        try {
            return userService.getUserPermissions(userId);
        } catch (Exception e) {
            logger.error("获取用户权限异常", e);
            return null;
        }
    }

    @Override
    public List<String> getUserRoles(String userId) {
        try {
            return userService.getUserRoles(userId);
        } catch (Exception e) {
            logger.error("获取用户角色异常", e);
            return null;
        }
    }

    /**
     * 生成令牌
     */
    private SSOToken generateToken(SSOUser user, String clientId) {
        try {
            // 生成访问令牌
            String accessToken = JWTUtil.generateToken(user);

            // 生成刷新令牌
            String refreshToken = UUID.randomUUID().toString().replace("-", "");

            // 创建令牌对象
            SSOToken token = new SSOToken(accessToken, refreshToken, SSOConstants.TOKEN_EXPIRE_TIME);
            token.setUserId(user.getUserId());
            token.setClientId(clientId);
            token.setScope("read write");

            // 存储令牌
            tokenService.storeToken(token);

            return token;

        } catch (Exception e) {
            logger.error("生成令牌异常", e);
            throw new RuntimeException("生成令牌失败", e);
        }
    }

    /**
     * 验证客户端
     */
    private boolean validateClient(String clientId, String clientSecret) {
        // TODO: 实现客户端验证逻辑
        return StringUtils.hasText(clientId) && StringUtils.hasText(clientSecret);
    }

    /**
     * 验证重定向URI
     */
    private boolean validateRedirectUri(String clientId, String redirectUri) {
        // TODO: 实现重定向URI验证逻辑
        return StringUtils.hasText(redirectUri);
    }
}
